package io;

import com.aliasi.chunk.Chunk;
import com.aliasi.chunk.Chunking;
import com.aliasi.coref.Mention;
import com.aliasi.coref.MentionChain;
import com.aliasi.tracker.Entity;
import com.aliasi.util.ObjectToSet;
import com.aliasi.util.Strings;
import com.aliasi.util.XML;
import com.aliasi.xml.DelegatingHandler;
import com.aliasi.xml.SAXWriter;
import com.aliasi.xml.TextAccumulatorHandler;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;


public class AceOutputDocument {

    private final String mId;
    private final Entity[] mEntities;
    private final MentionChain[] mMentionChains;
    private final String mSource;
    private HashSet<Entity> mSeenBefore = new HashSet();

    public AceOutputDocument(String id,String source,
                             Entity[] entities, MentionChain[] chains) {
        mId = id;
        mSource = source;
        mEntities = entities;
        mMentionChains = chains;
    }

    public String id() {
        return mId;
    }

    public String toString() {
        try {
            ByteArrayOutputStream bytesOut
                = new ByteArrayOutputStream();
            SAXWriter writer = new SAXWriter(bytesOut,Strings.UTF8);
            writer.startDocument();
            writer.characters("\n");
            writeTo(writer);
            writer.endDocument();
            byte[] bytes = bytesOut.toByteArray();
            return new String(bytes,Strings.UTF8);
        } catch (Exception e) {
            return "ERROR WRITING";
        }
    }

    void writeEntities(SAXWriter writer)
        throws SAXException, IOException {
        for (int i = 0; i < mEntities.length; ++i) {
            String id = String.valueOf(mEntities[i].id());
            if (mSeenBefore.contains(mEntities[i])) {
                System.out.println("Multiple entities for doc " + mId + " Ent: " + mEntities[i]);
                continue;
            }
            mSeenBefore.add(mEntities[i]);
            MentionChain mentionChain = mMentionChains[i];
            String entityType = mentionChain.entityType();
            String aceEntityType = null;
            String entitySubtype = null;
            if (entityType.equals(PERSON_TYPE)) {
                aceEntityType = "PER";
                entitySubtype = "Individual";
            } else if (entityType.equals(ORGANIZATION_TYPE)) {
                aceEntityType = "ORG";
                entitySubtype = "Government";
            }
            else {
                continue;
            }
            Attributes atts
                = SAXWriter
                .createAttributes(ID_ATT,id,
                                  CLASS_ATT, DEFAULT_CLASS,
                                  TYPE_ATT,aceEntityType,
                                  SUBTYPE_ATT,entitySubtype);
            writer.characters("\n\n");
            writer.startSimpleElement(ENTITY_ELT,atts);
            writer.startSimpleElement(ENTITY_ATTRIBUTES_ELT);
            writer.characters("\n");
            for (Mention mention : mentionChain.mentions()) {
                writer.startSimpleElement(NAME_ELT,NAME_ATT,mention.phrase());
                writer.endSimpleElement(NAME_ELT);
                writer.characters("\n");
            }
            writer.endSimpleElement(ENTITY_ATTRIBUTES_ELT);
            writer.endSimpleElement(ENTITY_ELT);
            writer.characters("\n");
        }
    }
    

    public void writeTo(SAXWriter writer)
        throws IOException, SAXException {

        Attributes atts
            = SAXWriter
            .createAttributes(URI_ATT,mId + ".sgm",
                              SOURCE_ATT,mSource,
                              AUTHOR_ATT,"LDC",
                              "TYPE","text");
        
        writer.startSimpleElement(SOURCE_FILE,atts);//needs to be read off the document
        writer.startSimpleElement(DOCUMENT,"DOCID",id());
        
        writeEntities(writer);
        writer.endSimpleElement(DOCUMENT);
        writer.endSimpleElement(SOURCE_FILE);
    }

    static final String PERSON_TYPE = "PER";
    static final String ORGANIZATION_TYPE = "ORG";
    //    static final String PERSON_TYPE = "PERSON";
    //static final String ORGANIZATION_TYPE = "ORGANIZATION";
    static final String SOURCE_FILE = "source_file";
    static final String SOURCE_ATT = "SOURCE";
    static final String URI_ATT = "URI";
    static final String AUTHOR_ATT = "AUTHOR";
    static final String DOCUMENT = "document";

    static final String ID_ATT = "ID";
    static final String CLASS_ATT = "CLASS";
    static final String DEFAULT_CLASS= "SPC";
    static final String TYPE_ATT = "TYPE";
    static final String SUBTYPE_ATT = "SUBTYPE";
    static final String DEFAULT_SUBTYPE = "Celestial";
    static final String ENTITY_ATTRIBUTES_ELT = "entity_attributes";
    static final String ENTITY_ELT = "entity";
    static final String NAME_ELT = "name";
    static final String NAME_ATT = "NAME";
    
}
